import json
from typing import Annotated

from arq import ArqRedis, create_pool
from fastapi import APIRouter, Depends, Form

from dc_shop.config import Settings
from dc_shop.database.models import CartProduct
from dc_shop.database.services.product import ProductService
from dc_shop.database.services.user import UserService
from dc_shop.webapp.app.providers.stub import Stub

cart_router = APIRouter(prefix="/cart", tags=["cart"])


@cart_router.post("/check")
async def check_cart(
    cart_data: Annotated[str, Form()],
    user_tg_id: Annotated[int, Form()],
    products_service: Annotated[ProductService, Depends(Stub(ProductService))],
    user_service: Annotated[UserService, Depends(Stub(UserService))],
):
    cart_data = json.loads(cart_data)
    user = await user_service.get_user_by_telegram_id(user_tg_id)

    cart_items = cart_data.get("items")
    for item in cart_items:
        available_quantity = await products_service.get_product_available_quantity(
            user.delivery_zone_id, item.get("id")
        )
        item["available_quantity"] = available_quantity

    return {
        "success": True,
        "items": cart_items,
    }


@cart_router.post("/create")
async def update_cart_products(
    cart_data: Annotated[str, Form()],
    user_tg_id: Annotated[int, Form()],
    user_service: Annotated[UserService, Depends(Stub(UserService))],
    config: Annotated[Settings, Depends(Stub(Settings))],
):
    error_msg = None
    arq_redis: ArqRedis = await create_pool(config.redis.pool_settings)

    cart_data = json.loads(cart_data)
    cart_items = cart_data.get("items")

    promocode_id = None
    promocode = cart_data.get("promocode")
    if promocode:
        promocode_id = promocode.get("id")

    cart_items = [CartProduct(product_id=item["id"], quantity=item["count"]) for item in cart_items]

    await user_service.delete_cart_items(user_tg_id)
    await user_service.update_user_cart(user_tg_id, cart_items)

    await arq_redis.enqueue_job("send_cart_confirmation_msg", user_tg_id=user_tg_id, promocode_id=promocode_id)

    return {"success": True, "error": error_msg}
